home *** CD-ROM | disk | FTP | other *** search
/ SIGGRAPH 1999: Conference Proceedings / SIGGRAPH 1999: Conference Proceedings.iso / pc / papers / tumblin / src_code.txt < prev    next >
Encoding:
Text File  |  1999-05-10  |  6.9 KB  |  136 lines

  1. /*
  2.  
  3. This is a C++ source code fragment for the LCIS function 
  4. described in the SIGGRAPH'99 paper 
  5.  
  6.     "LCIS: A Boundary Hierarchy For Detail-Preserving Contrast Reduction"
  7.     ----------------------------------------------------------------------
  8.     by Jack Tumblin and Greg Turk.
  9.  
  10.  
  11.   I offer this code only as an aid to people who may want to implement LCIS 
  12.   themselves.  This code was written to test and explore LCIS easily, not for
  13.   speed or efficiency. You may notice that the 'leakfix' and 'diffusion'
  14.   passes through the image could be combined to cut code size almost in half,
  15.   and that the code is full of expensive sqrt() calls and seemingly pointless
  16.   casts between PIXTYPE and double etc.; these are vestiges of earlier
  17.   experiments.  Though it is not elegant, it is readable and easy to debug.
  18.   Please use, share and modify this code in any way you wish.
  19.  
  20.   A few items in the code may need some explanation:
  21.   
  22.     --'Raw2D' and 'Raw3D' are my own floating-point image classes whose pixel
  23.         datatype is set by '#DEFINE PIXTYPE float'.  Both hold resizeable
  24.         arrays of pixels; Raw2D holds a 2D array indexed by (x,y), 
  25.         and Raw3D holds a 1D array of Raw2D objects, indexed by 'z'.  
  26.         In the code below, Raw3D objects all hold three Raw2D objects.
  27.  
  28.         member functions you'll see here include:
  29.             get(x,y)        -- returns the PIXTYPE pixel value at (x,y)
  30.             put(x,y,val)    -- write PIXTYPE value
  31.             sizer(arg)      -- set array size to match 'arg'
  32.             wipecopy(src)   -- copy contents of 'src', resize as needed.
  33.             ones()          -- set every pixel value to 1.0
  34.             zeros()         -- set every pixel value to 0.0
  35.  
  36.      --LCIS inputs:
  37.         The input image read from:
  38.             m_pA  --a pointer to a Raw3D image object; it holds 3 Raw2D
  39.                     objects, and we'll use the middle one of three.
  40.                     To read input pixel value at (x,y), do this:
  41.                     val = m_pA->get(x,y,1);
  42.  
  43.         Several user-settable parameters are held in a dialog box class;
  44.         these are:
  45.             --# of timesteps to run:      found at m_pParamDlg->m_diffusCount
  46.             --Conductance Threshold 'K';  found at m_pParamDlg->m_diffusKval
  47.             --Timestep length 'T';        found at m_pParamDlg->m_diffusTstep
  48.             --Leakfix enable/disable      found at M_pParamDlg->m_diffusLeakfix
  49.  
  50.     --LCIS outputs:
  51.         the output image is written to:
  52.             m_pOut  --a pointer to a Raw3D object; it holds 3 Raw2D  objects;
  53.                     two hold the current value for 'leakfix multipliers'
  54.                     (D_E,D_N in the paper), the other holds the result
  55.                     of the LCIS operation.
  56.                     m_pOut->z[0] holds the EW leakfix multiplier,
  57.                     m_pOut->z[1] holds the LCIS output image,
  58.                     m_pOut->z[2] holds the NS leakfix multipler.
  59.  
  60.     --Quick overview:
  61.         We begin by copying the input image to the output image object;
  62.         we never touch the input object again.  After initializing a few
  63.         pesky details, the LCIS code below uses just a few image objects: 
  64.         'src','bound' and 'm_pOut' (the output image object).  
  65.         
  66.         The 'src' object holds the result of the most recently completed 
  67.         timestep; we use 'src' as the source of all pixel information we need 
  68.         as we compute results of the current timestep and write them to m_pOut.
  69.         (m_pOut and src also hold the values of the leakfix multipliers for
  70.         each pixel). Once we finish finding all new pixel values for m_pOut, 
  71.         we copy m_pOut to src and start on the next timestep.
  72.  
  73.         For each timestep there are two passes through the entire image;
  74.         The first pass computes the 'leakfix multiplier' value for each 
  75.         link, and determines whether or not the link has become a 'boundary 
  76.         link'. If it has, we mark the pixels on either end of the link as 
  77.         a 'boundary pixel' by setting its value in the Raw2D image object 
  78.         called 'bound' to the value IS_BOUND_PIX.
  79.         
  80.         The second pass computes the flux through all links and applies the 
  81.         flux to the output image m_pOut.  However, it does not compute or 
  82.         apply any flux at all through any link with a boundary pixel on 
  83.         either end.  This accomplishes two goals:
  84.         --no flux will ever transform a ridge-like shock into a step-like
  85.             shock (prohibited by the LCIS PDEs--see dissertation for proof)
  86.         --no curvature estimate will use pixels that straddle a shock,
  87.             where curvature is (theoretically) infinite.
  88.  
  89.     If I've still failed to make this code clear to you and you're still
  90.     interested, send me a question by e-mail: ccsupjt@cc.gatech.edu;
  91.     if this is obsolete (I'm finally leaving Georgia Tech this fall) then
  92.     search the web for my website--I'll be there somewhere.
  93.  
  94.     Regards,
  95.     --Jack Tumblin
  96. */
  97.  
  98.  
  99.  
  100.  
  101. //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_
  102. //                                                             
  103. BOOL CFcnGroup::fcnLCIS4(CString & label)
  104. //------------------------------------------------------------------------------
  105. // Low Curvature Image Simplifier(LCIS)
  106. //
  107. //      K, timestep, leakfix enable, # iterations, 
  108. //      from SetFcnParam dialog class.
  109. //
  110. //------------------------------------------------------------------------------
  111. //      --prevents any curvature or motive force est. from using a set of pixels
  112. //      that straddles a 'shock', and
  113. //      --ensures that a 'shock' always forms a ridge discontinuity that never
  114. //      (due to smoothing within a region) evolves into a step discontinuity,
  115. //      mimicking the behavior of the PDE form of LCIS.
  116. // Heres how:
  117. //      --DEFINE: any pixel on either end of a link that contains a shock is a
  118. //              'Boundary Pixel', (shock==leakfix multiplier is >10.0)
  119. //      --APPLY: any link CONNECTED to a boundary pixel must have ZERO FLUX to
  120. //              ensure the boundary pixel will not change.
  121. //      Note that this scheme ADIABATIC and fully consistent with the 
  122. //      continuous PDE form of LCIS.
  123. //------------------------------------------------------------------------------
  124. // (Return 1 if successful; retn 0 if text 'label' does not match our internal 
  125. // name for this function; this is a double-check that index# used to select 
  126. // functions matches the desired function)
  127. {
  128. Raw2D src;                          // source img for each diffusion timestep.
  129. Raw2D bound;                        // boundary-pixel map.
  130.  
  131. int i,iE1,iE2,iW,j,jN1,jN2,jS,k,imax,jmax,kmax;     // image indices
  132. PIXTYPE N2val,N1val,Pval,S1val,W1val,E1val,E2val,NEval,NWval,SEval;
  133.                                     // neighborhood pixels: north,south,..
  134.                                     // (See LCIS paper, Figure 6)
  135. PIXTYPE Pxx2,Pyy2,Exx2,Eyy2,Nxx2,Nyy2,Nxy2,Sxy2,Wxy2;
  136.                                     // 2nd